use device_query::{DeviceQuery, DeviceState, Keycode};
use std::{error::Error, fmt::{Debug, Formatter}, fmt::Display, sync::mpsc::{SendError, Sender}};
use enigo::{
    Direction::{ Press, Release},
    Enigo, Key, Keyboard,  Settings
};
use std::time::Duration;
use std::thread;
use std::result::Result;
use arboard::{Clipboard};
// 自定义错误
#[derive(Debug)]
pub enum MyError {
    EnigoNewError(enigo::NewConError),
    EnigoInputError(enigo::InputError),
    ClipdError(arboard::Error),
}
impl Error for MyError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match &self {
            MyError::EnigoNewError(ref e) => Some(e),
            MyError::EnigoInputError(ref e) => Some(e),
            // 如果出现剪切板错误，那么很抱歉，没法啦
            MyError::ClipdError(ref e) => Some(e),
        }
    }
}
impl Display for MyError {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        // match 中， 可以使用 ref 来使变量所有不被转移，从而能在之后继续使用
        match &self {
            MyError::EnigoNewError(ref _e) => {
                write!(f, "Enigo New Error")
            },
            MyError::EnigoInputError(ref _e) => {
                write!(f, "Enigo Input Error")
            },
            MyError::ClipdError(ref _e) => {
                write!(f, "Clipd Error")
            },
        }
    }
}
impl From<enigo::NewConError> for MyError {
    fn from(value: enigo::NewConError) -> Self {
        MyError::EnigoNewError(value)
    }
}
impl From<enigo::InputError> for MyError {
    fn from(value: enigo::InputError) -> Self {
        MyError::EnigoInputError(value)
    }
}
impl From<arboard::Error> for MyError {
    fn from(value: arboard::Error) -> Self {
        MyError::ClipdError(value)
    }
}


// 按键比对
pub fn keysMatch(keys1 : &Vec<Keycode>, keys2 : &Vec<Keycode>) -> bool {
    let keys1_length = keys1.len();
    if keys1_length != keys2.len() {
        false
    } else {
        for i in 0..keys1_length {
            if keys1[i] != keys2[i] {
                return false;
            }
        }
        true
    }
}
// 全局按键检测线程
pub fn keyPressListen(target_keys : Vec<Keycode>, sender : Sender<u32>) {
    let mut cnt : u32 = 0;
    let device_state = DeviceState::new();
    loop {
        let keys : Vec<Keycode> = device_state.get_keys();
        // 跳过无按键时间
        if keys.len() == 0 { 
            cnt = 0;
            continue;
        }
        cnt += 1; // 筛选第一次按键事件
        if keysMatch(&keys, &target_keys) && (cnt == 1) {
            // 检测到按键，发送信号
            match sender.send(1) {
                Ok(_) => {
                    println!("Keys Occur!");
                }
                Err(SendError(_)) => {
                    return;
                }
            }
        }
    }
}

pub fn getSelectedText() -> Result<String, MyError>{
    let mut clpd = Clipboard::new()?;
    // 获取原本剪切板内容
    let text_origin = clpd.get_text()?;
    let mut enigo = Enigo::new(&Settings::default())?;
    enigo.key(Key::Control, Press)?;
    enigo.key(Key::C, Press)?;
    thread::sleep(Duration::from_millis(100));
    enigo.key(Key::C, Release)?;
    enigo.key(Key::Control, Release)?;
    let text_selected = clpd.get_text()?;
    // 恢复原本剪切板内容
    clpd.set_text(text_origin.clone())?;
    println!("原本剪切板内容：{}", text_origin);
    println!("选择内容：{}", text_selected);
    Ok(text_selected)
}